package com.blog.blogservice.domain.entity;

import com.blog.blogservice.app.service.PermissionService;
import com.blog.blogservice.app.service.RolePermissionService;
import com.blog.blogservice.app.service.RoleService;
import com.blog.blogservice.app.service.UserService;
import com.blog.blogservice.config.JwtToken;
import com.blog.blogservice.util.JwtUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 同时开启身份验证和权限验证，需要继承 AuthorizingRealm
 * 并实现其  doGetAuthenticationInfo()和 doGetAuthorizationInfo 两个方法
 */
public class ShiroRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private PermissionService permissionService;

    @Autowired
    private RolePermissionService rolePermissionService;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 查询数据库，将获取到的用户安全数据封装返回
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("这里验证--");
        // 从 AuthenticationToken 中获取当前用户
        JwtToken jwtToken = (JwtToken) token;
        String username = (String) jwtToken.getPrincipal();
        String tokenStr = (String) jwtToken.getCredentials();


        // 查询数据库获取用户信息，此处使用 Map 来模拟数据库
        UserEntity userEntity = new UserEntity();
        userEntity.setName(username);
        userEntity = userService.selectUser(userEntity);

        // 用户不存在
        if (userEntity == null) {
            throw new AuthenticationException("用户不存在！");
        }

        // 用户被锁定
        if (userEntity.getLocked()) {
            throw new LockedAccountException("该用户已被锁定,暂时无法登录！");
        }


        try {
            JwtUtils.verify(tokenStr, username, JwtUtils.TOKEN_SECRET);
        } catch (Exception e) {
            throw new AuthenticationException("该token非法，可能被篡改或过期");
        }

//        if (JwtUtils.isTokenExpired(tokenStr)) {
//            System.out.println("token 过期1");
//            JwtUtils.verify(tokenStr, username, userEntity.getPassword());
//            tokenStr = JwtUtils.refreshTokenExpired(tokenStr, userEntity.getPassword());
//            Boolean userBoolean = JwtUtils.verify(tokenStr, username, userEntity.getPassword());
//            if (!userBoolean) {
//                System.out.println("token 过期2");
//                throw new AuthenticationException("token 过期");
//            }else {
//
//            }
//        }else {
//            Boolean userBoolean = JwtUtils.verify(tokenStr, username, userEntity.getPassword());
//            if (!userBoolean) {
//                throw new AuthenticationException("token invalid");
//            }
//        }


        // 使用用户名作为盐值
        ByteSource credentialsSalt = ByteSource.Util.bytes(username);

        /**
         * 将获取到的用户数据封装成 AuthenticationInfo 对象返回，此处封装为 SimpleAuthenticationInfo 对象。
         */
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userEntity, tokenStr,
                getName());
        return info;
    }

    /**
     * 查询数据库，将获取到的用户的角色及权限信息返回
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("这里授权--");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 获取当前用户
        UserEntity currentUser = (UserEntity) SecurityUtils.getSubject().getPrincipal();

        // 查询数据库，获取用户的角色信息
        UserEntity userEntity = new UserEntity();
        userEntity.setName(currentUser.getName());
        //根据用户名得到关联角色
        List<Role> roleList = roleService.selectRoleByUserName(userEntity);
        if (!CollectionUtils.isEmpty(roleList)) {
            Set<String> roleSet = roleList.stream().map(Role::getName)
                    .map(String::valueOf).collect(Collectors.toSet());
            //角色关联权限
            List<RolePermission> rolePermissionList = rolePermissionService.selectPermissionByRoleName(roleList);
            info.setRoles(roleSet);
            if (!CollectionUtils.isEmpty(rolePermissionList)) {
                // 查询数据库，获取用户的权限信息
                List<Permission> permissionList = permissionService.selectPermission(rolePermissionList.stream()
                        .map(RolePermission::getPermissionId).collect(Collectors.toList()));
                if (!CollectionUtils.isEmpty(permissionList)) {
                    Set<String> permissionSet = permissionList.stream().map(Permission::getUrl).collect(Collectors.toSet());
                    info.setStringPermissions(permissionSet);
                }
            }
        }
        return info;
    }
}
